/**
 * PayRoller javascript library
 * v1.0
 * @author Rodrigo Longhi
 * @version 1.0
 */

/**
 * PayRoller: storage library for expense data
 * 
 * Definitions:
 * 
 * expenses: [] -> { id: 0, name: '', value: 0.00 }
 * 
 * group: [] -> { id: 0, name: '', split: [] }
 * 
 * split: [] -> { id: 0, type: 0..X, value: 0.00, handicap: 0.00 }
 * 
 * id: expense id type: 0..X -> 0: NONE 1: RELATIVE 2: DIVISION 3: FIXED
 */

// data content
Payroller = {

	// initialization function
	init: function() {

		// configure GUI components
		$('#tabs').tabs();
		$('#bt-reset, #bt-debug').button();

		$E.init();
		$G.init();
		$T.init();
	},

	// debug payroller data
	debug: function() {
		$U.debug();
	},

	// reset data
	reset: function() {
		localStorage.clear();
	},

	// return localStorage capability
	capable: function() {
		try {
			return 'localStorage' in window && window['localStorage'] !== null;
		} catch (e) {
			return false;
		}
	}
};

/**
 * Expenses interface:
 * 
 * Controls the expense data
 */
Payroller.expenses = {

	// DOM metadata
	_dialog: {
		name: 'dg-expense',
		focus: 'name',
		callback: function() { $E.save(); }
	},

	_table: {
		name: 'tb-expense',
		options: { edit: true, remove: true, ns: '$E' },
		columns: function() { return $E._columns; },
		fields: function() { return $E._fields; },
		values: function() { return $E.items; }
	},
	_columns: [{ label: 'ID', width: '15%' }, { label: 'Name', width: '55%' }, { label: 'Value', width: '20%' }],
	_fields: [{ name: 'id' }, { name: 'name' }, { name: 'value', prefix: 'R$ ' }],

	// essential properties
	key: 'payroller.expenses',
	lastId: 0,
	items: [],
	edit: null,

	// init expense interface
	init: function() {

		$U.dialog(this._dialog);

		$('#tab-expense button').button();
		$('#dg-expense-value').bind('keypress', function(e) {
			return Validations.currency(this, e);
		});

		// load expense data
		this.retrieve();
	},

	// opens the expense editor dialog
	open: function(expense, index) {
		$U.pop(this._dialog);
		
		this.edit = index;
		
		// if has id informed
		if (expense)
			$U.fill(this._dialog, expense);
	},

	// loads data from local storage
	retrieve: function() {
		this.items = $U.retrieve(this.key);
		this.lastId = $U.lastId;

		// redraw expense data
		this.draw();
	},

	// pushes the new expense into the collection
	save: function() {
		// TODO: validate
		if(this.edit != null) {
			this.items[this.edit].name = $('#dg-expense-name').val();
			this.items[this.edit].value = parseFloat($('#dg-expense-value').val());
		}else
			this.items.push({ id: this.newId(), name: $('#dg-expense-name').val(), value: $('#dg-expense-value').val() });
		
		// persist and redraw data
		this.draw();
		this.persist();
		$U.clean(this._dialog);
	},

	// remove expense
	remove: function(index) {
		this.items.splice(index, 1);

		// persist and redraw data
		this.draw();
		this.persist();
	},

	// save expense data into localStorage
	persist: function() {
		$U.persist({ key: this.key, values: this.items });
	},

	// gets new id for expense object
	newId: function() {
		return ++this.lastId;
	},

	// draw expense data into a table
	draw: function() {
		$U.draw(this._table);
	},
	
	// TODO: delete
	log: function() {
		$U.log($U.dump(this.items));
	}
};

Payroller.group = {

	// group METADATA
	_dialog: {
		name: 'dg-person',
		focus: 'name',
		callback: function() { $G.save(); }
	},
	
	_table: {
		name: 'tb-group',
		options: { edit: true, remove: true, ns: '$G' },
		columns: function() { return $G._columns; },
		fields: function() { return $G._fields; },
		values: function() { return $G.items; }
	},
	_columns: [{ label: 'ID', width: '15%' }, { label: 'Name', width: '75%' }],
	_fields: [{ name: 'id' }, { name: 'name' }],
	
	// essential properties
	key: 'payroller.group',
	lastId: 0,
	items: [],
	edit: null,

	// prepare group area
	init: function() {
		
		$U.dialog(this._dialog);
		$('#tab-group button').button();

		// get data
		this.retrieve();
	},
	
	// opens the person editor dialog
	open: function(person, index) {
		$U.pop(this._dialog);
		
		this.edit = index;
		
		// load split table
		$('#dg-person-tb-split').empty();
		
		// set header
		$('#dg-person-tb-split').append('<tr><th>Expense</th><th>Type</th><th>Value</th><th>Handicap</th></tr>');
		
		for (var i in $E.items) {
			$('#dg-person-tb-split').append('<tr>' +
				'<td>' + $E.items[i].name + '</td>' +
				'<td>' +
					'<select id="dg-split-type-' + $E.items[i].id + '">' +
						'<option value="0">0 - None</option>' +
						'<option value="1">1 - Relative</option>' +
						'<option value="2">2 - Division</option>' +
						'<option value="3">3 - Fixed</option>' +
					'</select>' +
				'</td>' +
				'<td><input type="text" id="dg-split-value-' + $E.items[i].id + '" size="4" /></td>' +
				'<td><input type="text" id="dg-split-handicap-' + $E.items[i].id + '" size="4" /></td>' +
			'</tr>');
		}
		
		// if has person informed
		if (person) {
			$U.fill(this._dialog, person);
			
			// fill split data
			for(var i in person.split) {
				var split = person.split[i];
				
				$('#dg-split-type-' + split.id).val(split.type);
				$('#dg-split-value-' + split.id).val(split.value);
				$('#dg-split-handicap-' + split.id).val(split.handicap);
			}
		}
		
		// attach events
		$('#dg-person-tb-split input[type=text]').bind('keypress', function(e) {
			return Validations.currency(this, e);
		});
	},

	// loads data from local storage
	retrieve: function() {
		this.items = $U.retrieve(this.key);
		this.lastId = $U.lastId;

		// redraw group data
		this.draw();
	},

	// save person information into the collection
	save: function() {
		// validate data
		// ...
		
		// remove item from list
		if(this.edit != null)
			this.items.splice(this.edit, 1);
		
		// fill split data
		var split = [];
		
		for(var i in $E.items) {
			//alert($E.items[i].id);
			split.push({
				id: $E.items[i].id,
				type: $('#dg-split-type-' + $E.items[i].id).val(),
				value: $('#dg-split-value-' + $E.items[i].id).val(),
				handicap: $('#dg-split-handicap-' + $E.items[i].id).val()});
		}
		
		this.items.push({ id: this.newId(), name: $('#dg-person-name').val(), split: split });
		
		// persist and redraw data
		this.draw();
		this.persist();
		$U.clean(this._dialog);
	},
	
	// TODO: remove person
	remove: function(index) {
		$U.log('Removing person: ' + index);
		this.items.splice(index, 1);
		
		// persist and redraw data
		this.draw();
		this.persist();
	},

	// save data into localStorage
	persist: function() {
		$U.persist({ key: this.key, values: this.items });
	},

	// gets new person id
	newId: function() {
		return ++this.lastId;
	},

	// draws the people involved table
	draw: function() {
		$U.draw(this._table);
	},
	
	// TODO: delete
	log: function() {
		$U.log($U.dump(this.items));
	}
};

Payroller.total = {
	init: function() {
		this.draw();
		$('#tab-totals button').button();
	},

	// draw total data in tablie
	draw: function() {

		// tax is used for individual expense values addressed by id, and total is the total amount
		var tax = {};
		var total = 0;

		// prepare expense values
		for(var i in $E.items) {
			tax[$E.items[i].id] = $E.items[i].value;
			total += $E.items[i].value;
		}
		
		// calculate handicap values
		for(var i in $G.items)
			for(var j in $G.items[i].split)
				if($G.items[i].split[j].handicap > 0)
					tax[$G.items[i].split[j].id] -= $G.items[i].split[j].handicap;
		
		// draw total table
		$('#tb-total').empty();
		$('#tb-total').append('<tr><th>Name</th><th>Debt</th><th>Paid</th><th>Refund</th></tr>');

		// fill person data
		for(var i in $G.items) {
			var debt = 0;
			
			// configure split data
			for(var j in $G.items[i].split) {
				var split = $G.items[i].split[j];
				
				switch(split.type) {
					case 1: // relative
						debt += tax[split.id] * (split.value / 100);
						break;
					case 2:	// division
						debt += tax[split.id] / split.value;
						break;
					case 3: // fixed
						debt += split.value;
						break;
				}
				
				// sum handicap
				debt += split.handicap;
			}
			
			$('#tb-total').append('<tr><td>' + $G.items[i].name + '</td><td>R$ ' + debt.toFixed(2) + '</td><td><input type="text" id="' + i + '-total-paid" size="8" /><button id="' + i + '-total-check"><img src="img/money.png" alt="Check" /></button></td><td id="' + i + '-total-refund"></td></tr>');
			
			// append debt to person
			$G.items[i].debt = debt;
		}

		// number validations
		$('#tb-total input').bind('keypress', function(e) {
			return Validations.currency(this, e);
		});
		
		// fill total line
		$('#tb-total').append('<tr><td align="right">Total: </td><td>R$ ' + total.toFixed(2) + '</td></tr>');
		
		// bind button events
		$('#tb-total button').button().bind('click', function(e) {
			var index = this.id.substring(0, 1);
			var paid = $('#' + index + '-total-paid');
			var tr = $('#' + index + '-total-refund');
			
			if(paid.val() == 0) return;
			
			// calculate refund data
			tr.html('R$ ' + (paid.val() - $G.items[index].debt).toFixed(2));
		});
	}
};

// redefine shorthands
if (typeof $E == 'undefined')
	$E = Payroller.expenses;
else
	alert('PayRoller Error: $E cannot be used.');

if (typeof $G == 'undefined')
	$G = Payroller.group;
else
	alert('PayRoller Error: $G cannot be used.');

if (typeof $T == 'undefined')
	$T = Payroller.total;
else
	alert('PayRoller Error: $T cannot be used.');